#include "globals.h"
#include "game.h"
#include "state_placetile.h"
#include "state_cursor.h"
#include "state_buystock.h"
#include "state_mergeoptions.h"
#include "state_mergerresolution.h"
#include "vector2.h"
#include <Windows.h>
#include <stdio.h>
#include <conio.h>

void Game::initStateMachine()
{
	queueState(new State_PlaceTile);
	m_stateQueue->peek()->init(this);
}

Game::Game(int numPlayers,int width, int height):m_running(true),userInput(0),turn(0),updates(0),inventoryPlayer(0){
	board = new Board(width, height);
	players = new Queue<Player>();
	players->setSizeUsed(numPlayers);
	Player * p;
	char * playerName;
	// give tiles to players
	for(int a = 0; a < 6; ++a)
	{
		for(int i = 0; i < players->size; ++i)
		{
			p = &players->list[i];
			Tile * nextTile = board->getRandomUnusedTile();
			if(nextTile)
				p->addTile(nextTile);
		}
	}
	// finish initializing players
	for(int i = 0; i < players->size; ++i)
	{
		playerName = new char[16];
		sprintf_s(playerName, 16, "player%d", i);
		p = &players->list[i];
		p->setName(playerName);
		p->orderTiles();
	}
	companies = new Queue<TileGroup>();
	companies->setSizeUsed(8);
	char * companyNames[] = {"??????","Xanatos","Stark","Umbrella","Tyrell","Wayne","LexCorp","Shinra"};
	int companyTier[] = {-1,2,2,1,1,1,0,0};
	int colors[] = {
		FOREGROUND_INTENSITY,
		FOREGROUND_RED|FOREGROUND_BLUE, 
		FOREGROUND_RED|FOREGROUND_GREEN,
		FOREGROUND_GREEN,
		FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY,
		FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY,
		FOREGROUND_RED|FOREGROUND_INTENSITY, 
		FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_INTENSITY, 
	};
	TileGroup * c;
	for(int i = 0; i < companies->size; ++i)
	{
		c = &companies->list[i];
		c->setup(companyNames[i], companyTier[i], colors[i]);
	}
	m_stateQueue = new Queue<GameState*>();
	currentPlayer = 0;
	companySelector = new CompanySelector(this,
		Vector2(board->getWidth()*Tile::DRAW_WIDTH, 0), companies);
	initStateMachine();
}

void Game::release()
{
	for(int i = 0; i < players->size; ++i)
	{
		delete [] players->list[i].getName();
	}
	delete m_stateQueue;
	delete companies;
	delete players;
	delete board;
}

void Game::draw(Graphics * g)
{
	int boardW = board->getWidth()*Tile::DRAW_WIDTH;
	int boardH = board->getHeight()*Tile::DRAW_HEIGHT;
	int companySelectorHeight = 9;
	GameState * state = m_stateQueue->peek();
	Player * p = getCurrentPlayer();
	// clear the screen
	g->clear(' ', Graphics::DEFAULT);
	// draw the board
	board->draw(g);
	// draw the player's inventory
	Player * invPlayer = inventoryPlayer?inventoryPlayer:p;
	invPlayer->drawInventory(g, Vector2(boardW, companySelectorHeight));
	// draw the current state information
	sprintf_s(g->TEXT, g->TEXT_SIZE, "%s%s", getCurrentPlayer()->getName(), state->getName());//stateName[inputState]);
	g->drawText(g->TEXT, 0, boardH, flashColor(2));
	// draw the company selector
	companySelector->draw(g);
	if(state)
	{
		state->draw(g);
	}
}

void Game::setInput(int a_input)
{
	switch(a_input){
	case 224:	// code for special characters
		a_input = _getch();
		switch(a_input){
		case 72:	a_input = 'w';	break;	// up
		case 75:	a_input = 'a';	break;	// left
		case 77:	a_input = 'd';	break;	// right
		case 80:	a_input = 's';	break;	// down
		}
		break;
	case 27:	// escape key. user wants to quit.
		m_running = false;
		break;
	}
	userInput = a_input;
}

void Game::processInput()
{
	if(m_stateQueue->size > 0)
		m_stateQueue->peek()->processInput(userInput);
	userInput = 0;
}

int Game::flashColor(int style){
#define ARR_SIZE(a)		(sizeof(a)/sizeof(a[0]))
	static int WHITE_TEXT[] = {// white
			Graphics::DARK_GRAY,
			Graphics::GRAY,
			Graphics::GRAY,
			Graphics::WHITE,
			Graphics::WHITE,
			Graphics::WHITE,
			Graphics::WHITE,
			Graphics::WHITE,
			Graphics::GRAY,
			Graphics::GRAY,
			Graphics::DARK_GRAY
		};
	static int WHITE_BACKGROUND[] = {// white background
			Graphics::DARK_GRAY|Graphics::BACK_INTENSITY,
			Graphics::GRAY|Graphics::BACK_INTENSITY,
			Graphics::GRAY|Graphics::BACK_INTENSITY,
			Graphics::WHITE|Graphics::BACK_INTENSITY,
			Graphics::WHITE|Graphics::BACK_INTENSITY,
			Graphics::WHITE|Graphics::BACK_INTENSITY,
			Graphics::WHITE|Graphics::BACK_INTENSITY,
			Graphics::WHITE|Graphics::BACK_INTENSITY,
			Graphics::GRAY|Graphics::BACK_INTENSITY,
			Graphics::GRAY|Graphics::BACK_INTENSITY,
			Graphics::DARK_GRAY|Graphics::BACK_INTENSITY
		};
	static int GREEN_TEXT[] = {// green
			Graphics::GREEN,
			Graphics::GREEN,
			Graphics::GREEN,
			Graphics::GREEN,
			Graphics::GREEN,
			Graphics::GREEN,
			Graphics::GREEN,
			Graphics::GREEN,
			Graphics::GREEN|Graphics::INTENSITY,
			Graphics::GREEN|Graphics::INTENSITY,
			Graphics::GREEN|Graphics::INTENSITY,
			Graphics::GREEN|Graphics::INTENSITY,
			Graphics::GREEN|Graphics::INTENSITY,
			Graphics::GREEN|Graphics::INTENSITY,
		};
	static int YELLOW_TEXT[] = {// yellow
			Graphics::DARK_GRAY,
			Graphics::RED|Graphics::GREEN,
			Graphics::RED|Graphics::GREEN|Graphics::INTENSITY,
			Graphics::RED|Graphics::GREEN|Graphics::INTENSITY,
			Graphics::RED|Graphics::GREEN,
			Graphics::DARK_GRAY
		};
	static int MUTED_TEXT[] = {// muted text
			Graphics::BLACK,
			Graphics::BLACK,
			Graphics::BLACK,
			Graphics::BLACK,
			Graphics::DARK_GRAY,
			Graphics::DARK_GRAY,
			Graphics::DARK_GRAY,
			Graphics::DARK_GRAY,
			Graphics::DARK_GRAY,
			Graphics::DARK_GRAY,
			Graphics::DARK_GRAY,
			Graphics::DARK_GRAY,
			Graphics::DARK_GRAY,
			Graphics::DARK_GRAY,
			Graphics::BLACK,
			Graphics::BLACK,
			Graphics::BLACK,
			Graphics::BLACK,
		};
	static int COLORS_SIZE[] = {
		ARR_SIZE(WHITE_TEXT),ARR_SIZE(WHITE_BACKGROUND),ARR_SIZE(GREEN_TEXT),
		ARR_SIZE(YELLOW_TEXT),ARR_SIZE(MUTED_TEXT)};
	static int * COLORS[] = {WHITE_TEXT,WHITE_BACKGROUND,GREEN_TEXT,YELLOW_TEXT,MUTED_TEXT,};

	return COLORS[style][updates % COLORS_SIZE[style]];
#undef ARR_SIZE
}
